<?php
declare(strict_types=1);
namespace SixShop\WechatPay\Service;

use SixShop\WechatPay\Config;
use think\facade\Log;
use WeChatPay\Crypto\AesGcm;
use WeChatPay\Crypto\Rsa;
use WeChatPay\Formatter;

class NotifyService
{
    public function __construct(private Config $config)
    {
    }

    /**
     * 微信支付成功回调
     * @param array $headers 请求头
     * @param string $inBody 请求体
     */
    public function transactionSuccess(array $headers, string $inBody):array
    {
        $signature = $headers['Wechatpay-Signature'] ?? '';// 请根据实际情况获取
        $timestamp = $headers['Wechatpay-Timestamp'] ?? '';// 请根据实际情况获取
        $serial = $headers['Wechatpay-Serial'] ?? ''; // 请根据实际情况获取
        $nonce = $headers['Wechatpay-Nonce'] ?? ''; // 请根据实际情况获取
        
        $apiv3Key = $this->config->api_v3_key;
        $platformPublicKeyInstance = $this->config->platform_cert;

        $timeOffsetStatus = 300 >= abs(Formatter::timestamp() - (int)$timestamp);
        if (!$timeOffsetStatus) {
            throw new \RuntimeException('The timestamp is out of range.');
        }
        $verifiedStatus = Rsa::verify(
        // 构造验签名串
            Formatter::joinedByLineFeed($timestamp, $nonce, $inBody),
            $signature,
            $platformPublicKeyInstance
        );
        if (!$verifiedStatus) {
            // TODO
            Log::warning('The signature is invalid. timestamp={timestamp} nonce={nonce} inBody={inBody} signature={signature}', [
                'timestamp' => $timestamp,
                'nonce' => $nonce,
                'inBody' => $inBody,
                'signature' => $signature,
            ]);
            //throw new \RuntimeException('The signature is invalid.');
        }
        // 转换通知的JSON文本消息为PHP Array数组
        $inBodyArray = (array)json_decode($inBody, true);
        // 使用PHP7的数据解构语法，从Array中解构并赋值变量
        ['resource' => [
            'ciphertext' => $ciphertext,
            'nonce' => $nonce,
            'associated_data' => $aad
        ]] = $inBodyArray;
        // 加密文本消息解密
        $inBodyResource = AesGcm::decrypt($ciphertext, $apiv3Key, $nonce, $aad);
        return json_decode($inBodyResource, true);
    }
}